In this lecture, we're going to be creating bullet holes that will appear on any surface that is hit
by our bullets.
So if I pull out my gun and I shoot, as you can see, bullet holes appear at where our bullets hit.
And then if I pull out my shotgun and shoot, as you can see, there is the spread from all of the pellets
shot out of our shotgun.
So let's get started.
Back inside of our guns handler script.
Let's go ahead and create a function for creating a bullet hole.
I'll call this function create bullet hole.
And we can get past the properties for a particular gun.
So that way we set the size of the bullet hole to the correct size.
And then we also want to grab the result or that raycast information from the client side raycast.
Then we can go ahead and check in this function.
If there is a raycast result.
If there is no result, then we're just going to return because there's nothing to create a bullet hole
on.
Otherwise we can go ahead and get that instance that we hit, which is going to be equal to our result
dot raycast result and get that instance.
And then we can go ahead and create a new bullet hole.
And that's going to be inside of replicated storage, shared parts.
And our bullet hole is inside of there and we're going to clone that.
And then we're going to make sure to un anchor our bullet hole, because we want to weld this bullet
hole to whatever part it hit.
That way, if the part that we hit belongs to a limb of another character model, that bullet hole will
move along with that limb.
So we'll also create a new weld here instance dot new weld constraint.
And then part zero for the weld is going to be equal to our bullet hole.
And then the part one for our weld is going to be equal to the instance we hit.
Then we can go ahead and set the parent of the weld equal to the bullet hole.
And now what we want to do is we want to go ahead and get the offset between the position of our instance
and where we hit on our instance.
So if you remember, the client sends us information of where the position of the instance was.
And then we also get past the information of where exactly we ray casted and hit a point at.
So I'm going to create a variable.
I'm going to call it offset.
And it's going to be equal to my result dot raycast result dot position.
And I'm going to subtract this by my result dot instance position.
That way I'm getting this offset between the position of my instance and where we hit.
And then using this offset we can go ahead and calculate where we should position our bullet hole based
on the position of the instance on the server.
So we're going to call this our server key frame offset.
And that's going to be equal to a key frame dot new.
And the position is going to be the instance position.
But then we also want to add a key frame that's going to be the offset that we just calculated right
here.
So key frame dot new.
And we're going to calculate it with this offset.
Now that we have the position where we should set our bullet hole, we can go ahead and update the properties
of our bullet hole.
For example we can update the size to be equal to the properties dot bullet hole size.
And then we can also update the key frame of our bullet hole to be equal to.
And we're going to create a new key frame.
And it's going to be at our server keyframe offset position.
And I want this keyframe to be looking in a particular direction.
And the direction that I want the bullet to look at needs to be the same normal vector of the face we
hit.
For example, if we were to hit, let's say this part right here, then I want to match up the rotation
of our bullet hole to be flush or parallel with the surface.
So you can imagine the normal vector for this face right here is going to be pointing out this way.
So I want the keyframe of my bullet hole to be set at that position, while also looking in that direction
of the normal vector.
And that's going to be very easy to do.
We can use actually the look at.
Function.
And where we want to look at is going to be at our server C frame offset dot position.
And then we want to offset this position by the result dot raycast result dot normal.
So you can imagine this is a new position that is one stud in front of where we hit at our raycast and
the direction of wherever our face that we hit is looking towards.
So now that we've set the bullet hole at the correct position, we can go ahead and set the parent of
the bullet hole, and I'm going to place it in the workspace dot filtering folder, and I'm going to
put it in the bullet holes folder.
Then the other thing I actually want to do is I want to go ahead and update the color of my bullet hole
to match the color of whatever part it hit.
So, in fact, inside of the bullet hole, we're going to find the decal that's in there.
So find First Child which is a decal.
And we want to update the color three of this decal to be equal to the instance dot color.
Then once we do that, we can go ahead and emit some particles out of our bullet hole.
So bullet hole we'll get the particle emitter.
And we're going to firstly update the color of the particles as well to match the color of the instance.
So we're going to make a new color sequence dot new.
And we're going to pass the instance dot color.
And then for the bullet hole dot particle emitter we're going to emit.
According to the properties.
Dot bullet hole.
Particle amount.
And just like that, we have our bullet hole complete.
Now, we don't want those bullet hole to remain on the map forever.
So what we can go ahead and do is actually grab the debris service.
So debris equal game get service debris.
And then we can go ahead and clean up this bullet hole off of the map after a set period of time.
So we're going to add an item to the debris service.
And the item is going to be our bullet hole.
And we can go ahead and wait for maybe I don't know something like 10s.
So after 10s the bullet hole will disappear and be destroyed.
Now that we have our function complete, we can go ahead and call our function from our shoot function.
So when we calculate the damage, we also want to go ahead and create a bullet hole for a pellet.
So we'll pass the properties and then the pellet result.
And then we want to do the same thing down here.
We're going to create a bullet hole pass the properties as well as the args which is the result.
So now if we go and play test our game and we are to shoot our guns, we should see a bullet hole appear
at wherever we shot.
And let's say I shoot right there and I click.
As you can see now, our bullet hole has appeared.
And as you can see, it's also flush or parallel with the surface that we hit right here.
It's matching the Or.
It's looking towards the normal vector of this face.
And then you can see it disappeared as well because the debris service cleaned it up for us.
And again we can shoot any surface.
And as you can see the bullet holes are matching the normal vector of the surface they're hitting.
I can also shoot some other stuff, for example, this bench with my shotgun.
So if I click.
As you can see, each of our individual pellets flew out of our shotgun and hit the different parts
that made up our bench.
And of course, keep shooting.
And there you go.
You can see the spread of all the pellets coming out of our shotgun, and the bullet holes for each
one of those pellets.
So let me go ahead and shoot something else like this.
If I shoot, there's all my bullets, and if I back up farther away, my bullets should be spread out
more.
So if I shoot again.
And then let's go take a look.
As you can see, the bullets spread out a lot more from my shotgun.
Very cool.
In the next lecture, we're going to continue adding new features to our guns, such as animations.
So I'll see you in the next one.